/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.easoft.code.pos.ui.controllers;

import com.easoft.code.pos.App;
import com.easoft.code.pos.data.dao.GenericDao;
import com.easoft.code.pos.data.exception.CoreDataLayerException;
import com.easoft.code.pos.data.pojos.Bodega;
import com.easoft.code.pos.data.pojos.DocumentoOper;
import com.easoft.code.pos.data.pojos.DocumentoOperTipo;
import com.easoft.code.pos.data.pojos.MovimientoInv;
import com.easoft.code.pos.data.pojos.MovimientoInvDet;
import com.easoft.code.pos.data.pojos.Persona;
import com.easoft.code.pos.data.pojos.PosCaja;
import com.easoft.code.pos.data.pojos.PosFactura;
import com.easoft.code.pos.data.pojos.PosFacturaPK;
import com.easoft.code.pos.data.pojos.PosSerieFactura;
import com.easoft.code.pos.data.pojos.PosUsuario;
import com.easoft.code.pos.data.pojos.Producto;
import com.easoft.code.pos.data.util.QueryParameter;
import com.easoft.code.pos.integration.cae.bean.XmlCae;
import com.easoft.code.pos.integration.cae.proceso.GeneraCae;
import com.easoft.code.pos.integration.cae.util.UtilsString;
import com.easoft.code.pos.ui.beans.pos.POSItem;
import com.easoft.code.pos.ui.beans.pos.POSOperation;
import com.easoft.code.pos.util.Valores;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;

/**
 *
 * @author Eliu
 */
public class POSController {

    private GenericDao dao = GenericDao.getMe();

    /**
     *
     * @param p
     * @return
     * @throws CoreDataLayerException
     */
    public Producto getProductoByCodigo(Producto p) throws CoreDataLayerException {
        if (p.getCodigo() != null && !p.getCodigo().isEmpty()) {
            try {
                return (Producto) dao.doNamedQuery("Producto.findByCodigo", new QueryParameter[]{
                    new QueryParameter(
                    "codigo", p.getCodigo())}, Producto.class, true);
            } catch (CoreDataLayerException ex) {
                throw ex;
            }
        }
        if (p.getCodigoBarra() != null && p.getCodigoBarra().isEmpty()) {
            try {
                return (Producto) dao.doNamedQuery("Producto.findByCodigoBarra", new QueryParameter[]{
                    new QueryParameter(
                    "codigoBarra", p.getCodigoBarra())}, Producto.class, false);
            } catch (CoreDataLayerException ex) {
                throw ex;
            }
        }

        return null;
    }

    /**
     *
     * @param nit
     * @param name
     * @param direccion
     * @param create
     * @return
     * @throws CoreDataLayerException
     */
    public Persona validateCliente(String nit, String name, String direccion, boolean create) throws CoreDataLayerException {
        Persona c = (Persona) dao.doNamedQuery("Persona.findByCodigo", new QueryParameter[]{
            new QueryParameter("codigo", nit)},
                Persona.class, true);
        if (c == null && create) {
            Object[] options = {"Si, Crear nuevo",
                "No, Ingresar otro"};
            int n = JOptionPane.showOptionDialog(App.mainForm,
                    "El cliente no existe desea crearlo?",
                    "Cliente",
                    JOptionPane.YES_NO_OPTION,
                    JOptionPane.QUESTION_MESSAGE,
                    null,
                    options,
                    options[0]);
            if (n == 0) {
                c = new Persona();
                c.setCodigo(nit);
                c.setNombre(name);
                c.setDireccion(direccion);
                c.setTelefono(" ");
                c.setTipoPersona(1);
                dao.save(c);
            }
        }
        return c;
    }

    /**
     *
     * @param c
     * @throws CoreDataLayerException
     */
    public void crearCliente(Persona c) throws CoreDataLayerException {
        dao.save(c);
    }

    /**
     *
     * @return @throws CoreDataLayerException
     */
    public List<Persona> getAllClientes() throws CoreDataLayerException {
        return (List<Persona>) dao.doNamedQuery("Persona.findAll", new QueryParameter[]{},
                Persona.class, false);
    }

    public PosCaja getCaja(Integer idCaja) throws CoreDataLayerException {
        return (PosCaja) dao.doNamedQuery("PosCaja.findById", new QueryParameter[]{
            new QueryParameter("id", idCaja)},
                PosCaja.class, true);
    }

    public Bodega getBodega(Integer idBodega) throws CoreDataLayerException {
        return (Bodega) dao.doNamedQuery("Bodega.findById", new QueryParameter[]{
            new QueryParameter("id", idBodega)},
                Bodega.class, true);
    }

    public DocumentoOperTipo getPOSDefaultOper() {
        try {
            return (DocumentoOperTipo) dao.doNamedQuery("DocumentoOperTipo.findById",
                    new QueryParameter[]{new QueryParameter("id", Integer.valueOf(Valores.getConfigValue(Valores.POS_DEF_OPER)))},
                    DocumentoOperTipo.class, true);
        } catch (CoreDataLayerException ex) {
            Logger.getLogger(POSController.class.getName()).log(Level.SEVERE, null, ex);
        }
        return null;
    }

    /**
     *
     * @param operation
     * @return
     * @throws CoreDataLayerException
     */
    public PosFactura saveOperation(POSOperation operation) throws CoreDataLayerException {
        PosFactura fac = new PosFactura();
        PosFacturaPK pk = getNextFactura();
        MovimientoInv mov = new MovimientoInv();
        PosCaja caja = getCaja(App.caja);
        Bodega bodega = getBodega(caja.getDefBodega().getId());
        PosUsuario user = new PosUsuario("eliu");
        DocumentoOperTipo docTipo = getPOSDefaultOper();
        try {
            fac.setPosFacturaPK(pk);
            fac.setFechaEmision(Calendar.getInstance().getTime());
            fac.setTotal(operation.getTotal().floatValue());
            fac.setPosUsuario(user);
            fac.setPosCaja(caja);
            fac.setEstado(1);

            fac.setDescuento(operation.getDescuento().floatValue());
            fac.setTotalReal(fac.getTotal() - fac.getDescuento());
            dao.save(fac);
        } catch (CoreDataLayerException ex) {
            throw ex;
        }
        try {
            DocumentoOper docOper = new DocumentoOper();
            docOper.setSerie(docTipo.getDocumentoResolucion());
            docOper.setNumero(new InventariosMovController().getNextDocNumber(docTipo.getDocumentoResolucion()));
            docOper.setMovimientoInvCollection(new LinkedList<MovimientoInv>());
            docOper.setTotal(operation.getTotal().floatValue());
            docOper.setDescuento(operation.getDescuento().floatValue());
            docOper.setEfectivo(operation.getEfectivo().floatValue());
            docOper.setTarjeta(operation.getTarjeta().floatValue());
            docOper.setCredito(operation.getCredito().floatValue());
            docOper.setFecha(fac.getFechaEmision());
            docOper.setCheque(0f);
            docOper.setDoctoOperTipo(docTipo);
            docOper.setEstado(Valores.OPER_APLICADO);
            docOper.setPersonaId(operation.getCliente());
            docOper.setPersonaTipo(docOper.getPersonaId().getTipoPersona());

            mov.setTotal(docOper.getTotal());
            mov.setDocumentoMovId(docOper);
            mov.setBodega(bodega);
            mov.setFechaEmision(fac.getFechaEmision());
            mov.setOperacionInv(docTipo.getOperacionInv());
            mov.setDocumentoMovId(docOper);
            mov.setPosUsuario(user);
            mov.setBodega(bodega);
            mov.setEstado(docOper.getEstado());
            mov.setMovimientoInvDetCollection(new LinkedList<MovimientoInvDet>());
            double descuento = 0d;
            for (POSItem i : operation.getItems()) {
                double detDesc = i.getCantidad() * (i.getDescuentoAuto() + i.getDescuentoManual());
                MovimientoInvDet det = new MovimientoInvDet();
                det.setCantidad(i.getCantidad().floatValue());
                det.setDescuentoAuto(i.getDescuentoAuto().floatValue() * i.getCantidad().intValue());
                det.setDescuentoManual(i.getDescuentoManual().floatValue() * i.getCantidad().intValue());
                det.setTotal(i.getSubtotal().floatValue());
                det.setTotalNeto((float) (i.getSubtotal().floatValue() - detDesc));
                det.setPrecioVenta(i.getPrecio().floatValue());
                det.setPrecioCosto(i.getProducto().getPrecioCosto());
                det.setProductoCodigo(i.getProducto());
                det.setGanancia(i.getCantidad().floatValue() * (det.getPrecioVenta() - det.getPrecioCosto()));
                det.setMovimientoInvId(mov);
                descuento = descuento + detDesc;
                mov.getMovimientoInvDetCollection().add(det);
            }
            docOper.getMovimientoInvCollection().add(mov);

            dao.save(docOper);

            return fac;
        } catch (CoreDataLayerException ex) {
            throw ex;
        }
    }

    /**
     *
     * @return
     */
    private PosFacturaPK getNextFactura() throws CoreDataLayerException {
        try {
            PosSerieFactura s = (PosSerieFactura) dao.doNamedQuery("PosSerieFactura.findByEstado",
                    new QueryParameter[]{
                        new QueryParameter("estado", 1)},
                    PosSerieFactura.class, true);
            PosFacturaPK pk = new PosFacturaPK();
            if (s == null) {
                return null;
            }
            pk.setSerie(s.getSerie());
            Number next = (Number) dao.doSQL("Call getNextNumeroFactura(:serie)",
                    new QueryParameter[]{new QueryParameter("serie", s.getSerie())},
                    Number.class, true, false);
            pk.setNumero(next.toString());

            return pk;
        } catch (CoreDataLayerException ex) {
            ex.printStackTrace(System.err);
            throw ex;
        }
    }

    /**
     *
     * @param f
     * @return
     */
    private String getFirmaFactura(PosFactura f) {
        Float iva = Float.valueOf(Valores.getCAEConfigValue("cae.iva"));
        Float neto = (f.getTotalReal() / iva);
        Float fIva = f.getTotalReal() - neto;
        SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
        String folio = (Calendar.getInstance().get(Calendar.YEAR) - 2000) + "-"
                + UtilsString.fill(f.getPosFacturaPK().getNumero(), 10, '0', UtilsString.LEFT);
        System.out.println(folio);
        XmlCae cae = GeneraCae.GenCae(f.getPosFacturaPK().getSerie(),
                Valores.getCAEConfigValue("cae.folio"), null,
                Valores.getCAEConfigValue("cae.nitemisor"),
                Valores.getCAEConfigValue("cae.nitgface"),
                sd.format(f.getFechaEmision()) + " 00:00:00",
                Valores.getCAEConfigValue("cae.noautorizacion"), neto.toString(), fIva.toString(),
                f.getTotal().toString(), Calendar.getInstance().get(Calendar.YEAR) + "",
                Valores.getCAEConfigValue("cae.tipofac"));
        return cae.getCae();
    }
}
